package com.lfy.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lfy.cache.ExistCache;

import com.lfy.domain.vo.BackGroundVO;
import com.lfy.modules.common.config.sys.DictionariesKey;
import com.lfy.modules.common.config.sys.SysDictionaries;
import com.lfy.modules.blog.domain.dto.article.CommentDTO;
import com.lfy.domain.dto.FeedBackDTO;
import com.lfy.domain.vo.SayHomeVO;
import com.lfy.domain.vo.SayVO;
import com.lfy.modules.blog.cache.ArticleDetailCache;
import com.lfy.modules.blog.domain.event.ClearWebArticleDetailEvent;
import com.lfy.modules.blog.domain.vo.web.ArticleCommentVO;
import com.lfy.modules.blog.domain.vo.web.ArticleTextVO;
import com.lfy.modules.blog.cache.HomeCache;
import com.lfy.modules.blog.domain.*;
import com.lfy.modules.blog.domain.event.ClearHomeArticleCacheEvent;
import com.lfy.modules.blog.domain.vo.feedback.FeedbackVO;
import com.lfy.modules.blog.domain.vo.web.ArticleShowVO;
import com.lfy.modules.blog.domain.vo.web.FeedbackWebVO;
import com.lfy.modules.blog.domain.vo.web.HomeDetailVO;
import com.lfy.modules.blog.domain.vo.web.HomeVO;
import com.lfy.modules.blog.mapper.BlogArticleMapper;
import com.lfy.modules.blog.service.*;
import com.lfy.modules.common.custom.constants.*;
import com.lfy.modules.common.domain.BaseEnum;
import com.lfy.modules.common.domain.PageResultVO;
import com.lfy.modules.common.domain.R;
import com.lfy.modules.common.domain.entity.UserEntity;
import com.lfy.modules.common.utils.PageUtil;
import com.lfy.modules.common.utils.RequestUtil;
import com.lfy.modules.letter.domain.SiteLetterEntity;
import com.lfy.modules.letter.domain.builder.Letter;
import com.lfy.modules.letter.domain.builder.LetterEnum;
import com.lfy.modules.letter.domain.event.LetterEvent;
import com.lfy.service.WebService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
/**
 * web
 *
 * @author <a href="https://www.lvfeiy.top">lfy</a>
 * @date 2024/5/15 14:42
 */
@Service
@Slf4j
public class WebServiceImpl implements WebService {
    @Resource
    private UserService userService;
    @Resource
    private HomeDetailService homeDetailService;
    @Resource
    private ThreadPoolExecutor mainThreadPool;
    @Resource
    private BlogArticleMapper blogArticleMapper;
    @Resource
    private ArticleCommentService articleCommentService;
    @Resource
    private ArticleTagService articleTagService;
    @Resource
    private ArticleClassificationService articleClassificationService;
    @Resource
    private ArticleTextService articleTextService;
    @Resource
    private FeedbackService feedbackService;
    @Resource
    private MoodService moodService;
    @Resource
    private SocialService socialService;

    @Override
    public R<HomeVO> home(String url) {
        Long userId = checkUrl(url);
        if (Objects.isNull(userId)) {
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        HomeVO cache = HomeCache.get(userId);
        if (!Objects.isNull(cache)) {
            return R.success(cache);
        }
        synchronized (ExistCache.HOME_PREFIX.concat(userId.toString()).intern()) {
            HomeVO homeCache = HomeCache.get(userId);
            if (!Objects.isNull(homeCache)) {
                return R.success(homeCache);
            }
            HomeVO homeVO = new HomeVO();
            HomeDetailVO homeDetailVO = new HomeDetailVO();
            String prefix = SysDictionaries.getValue(DictionariesKey.SYS_MINIO_SITE);
            //主页


            CompletableFuture<Void> homeFuture = CompletableFuture.runAsync(() -> {

                HomeDetail detail = homeDetailService.getOne(new LambdaQueryWrapper<HomeDetail>().eq(HomeDetail::getTenantId,userId));
                detail.setFm(prefix.concat(detail.getFm()));
                detail.setAuthorHeaderImg(prefix.concat(detail.getAuthorHeaderImg()));
                BeanUtils.copyProperties(detail, homeDetailVO);
                R<PageResultVO<FeedbackVO>> feedbackList = feedbackService.getFeedbackList(2, 1, userId);
                if(feedbackList.getCode().equals(BaseEnum.commonEnum.SUCCESS.getCode()) && Objects.nonNull(feedbackList.getData())){
                    PageResultVO<FeedbackVO> data = feedbackList.getData();
                    List<FeedbackVO> list = data.getList();
                    if(CollectionUtils.isNotEmpty(list)){
                        List<FeedbackWebVO> vos = list.stream().map(item -> {
                            FeedbackWebVO feedbackWebVO = new FeedbackWebVO();
                            feedbackWebVO.setMsg(item.getText());
                            feedbackWebVO.setStatus(FeedbackEnum.getStatus(item.getStatus()));
                            feedbackWebVO.setDate(item.getCreateTime());
                            return feedbackWebVO;
                        }).collect(Collectors.toList());
                        PageResultVO<FeedbackWebVO> feedResult = PageUtil.convertPageVO(data, vos);
                        homeVO.setFeedbackList(feedResult);
                    }else {
                        homeVO.setFeedbackList(PageUtil.convertEmptyPageVO(data, FeedbackWebVO.class));
                    }
                }

            }, mainThreadPool);
            //文章详情
            CompletableFuture<Void> articleFuture = CompletableFuture.runAsync(() -> {

                R<PageResultVO<ArticleShowVO>> articleResult = getArticleList(1, 5, userId, null);
                if (Objects.nonNull(articleResult) && BaseEnum.commonEnum.SUCCESS.getCode().equals(articleResult.getCode()) && Objects.nonNull(articleResult.getData())) {
                    homeVO.setArticleVOList(articleResult.getData());
                }

            }, mainThreadPool);
            //标签数，分类数,推荐文章
            CompletableFuture<Void> tagAndCategoryCountFuture = CompletableFuture.runAsync(() -> {

                int tagCount = articleTagService.count(new LambdaQueryWrapper<ArticleTagEntity>().eq(ArticleTagEntity::getTenantId, userId));
                int catCount = articleClassificationService.count(new LambdaQueryWrapper<ArticleClassificationEntity>().eq(ArticleClassificationEntity::getTenantId, userId));
                homeDetailVO.setTagCount(tagCount);
                homeDetailVO.setCategoryCount(catCount);
                List<ArticleEntity> articleEntities = this.blogArticleMapper.selectList(new LambdaQueryWrapper<ArticleEntity>().eq(ArticleEntity::getTenantId, userId).eq(ArticleEntity::getRecommend, ArticleEnum.RECOMMEND.getCode()).eq(ArticleEntity::getStatus, ArticleEnum.UP.getCode()).orderByDesc(ArticleEntity::getSortNum));
                if (CollectionUtils.isNotEmpty(articleEntities)) {
                    List<ArticleShowVO> showVOS = articleEntities.stream().map(item -> {
                        ArticleShowVO articleShowVO = new ArticleShowVO();
                        BeanUtils.copyProperties(item, articleShowVO);
                        articleShowVO.setArticleImages(prefix+item.getArticleImages());
                        //发布时间
                        articleShowVO.setCreateTime(DateUtil.formatDateTime(item.getCreateTime()));
                        //更新时间
                        articleShowVO.setUpdateTime(DateUtil.formatDateTime(item.getUpdateTime()));
                        return articleShowVO;
                        //TODO 推荐文章，这里只显示了三个
                    }).limit(3).collect(Collectors.toList());
                    homeVO.setRecommendArticleList(showVOS);
                }else {
                    homeVO.setRecommendArticleList(new ArrayList<>());
                }

            }, mainThreadPool);
            //文章数、7、30、360天新增文章数
            CompletableFuture<Void> articleCountFuture = CompletableFuture.runAsync(() -> {

                Integer count = blogArticleMapper.selectCount(new LambdaQueryWrapper<ArticleEntity>().eq(ArticleEntity::getTenantId,userId));
                homeDetailVO.setArticleCount(count);
                //7天新增文章数
                Integer sevenDayCount = blogArticleMapper.selectCount(new LambdaQueryWrapper<ArticleEntity>()
                        .eq(ArticleEntity::getTenantId, userId)
                        .ge(ArticleEntity::getCreateTime, DateUtil.offsetDay(DateUtil.date(), -7)));

                homeDetailVO.setArticleServenCount(sevenDayCount);
                //30天新增文章数
                Integer thirtyDayCount = blogArticleMapper.selectCount(new LambdaQueryWrapper<ArticleEntity>()
                        .eq(ArticleEntity::getTenantId,userId)
                        .ge(ArticleEntity::getCreateTime, DateUtil.offsetDay(DateUtil.date(), -30)));

                homeDetailVO.setArticleThirtyCount(thirtyDayCount);
                //360天新增文章数
                Integer thirtySixtyDayCount = blogArticleMapper.selectCount(new LambdaQueryWrapper<ArticleEntity>()
                        .eq(ArticleEntity::getTenantId, userId)
                        .ge(ArticleEntity::getCreateTime, DateUtil.offsetDay(DateUtil.date(), -360)));

                homeDetailVO.setArticleThirtySixtyCount(thirtySixtyDayCount);

            }, mainThreadPool);
            CompletableFuture.allOf(homeFuture, articleFuture,articleCountFuture,tagAndCategoryCountFuture).join();
            homeVO.setHomeDetail(homeDetailVO);
            HomeCache.put(userId, homeVO);

            return R.success(homeVO);

        }

    }

    @Override
    public R<PageResultVO<ArticleShowVO>> getArticleList(int pageNum, int pageSize, Long userId, String url) {
        if (pageSize > 20) {
            return R.error("分页异常");
        }
        if (Objects.isNull(userId)) {
            UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));
            if (Objects.isNull(user)) {
                return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
            }

            userId = user.getId();
        }
        Page<ArticleEntity> page = new Page<>(pageNum, pageSize);
        Page<ArticleEntity> articleEntityPage = blogArticleMapper.selectPage(page, new LambdaQueryWrapper<ArticleEntity>().eq(ArticleEntity::getTenantId, userId).eq(ArticleEntity::getStatus, ArticleEnum.UP.getCode()).orderByDesc(ArticleEntity::getSortNum).orderByDesc(ArticleEntity::getCreateTime));
        List<ArticleEntity> records = articleEntityPage.getRecords();
        if (!CollectionUtils.isEmpty((records))) {
            Set<Long> ids = records.stream().map(ArticleEntity::getId).collect(Collectors.toSet());
            List<ArticleComment> articleComments = articleCommentService.list(new LambdaQueryWrapper<ArticleComment>().in(ArticleComment::getArticleId, ids));

            List<ArticleTagEntity> tags = articleTagService.list(new LambdaQueryWrapper<ArticleTagEntity>().eq(ArticleTagEntity::getTenantId, userId));
            List<ArticleShowVO> articleShowVOS = records.stream().map(item -> {
                ArticleShowVO articleShowVO = new ArticleShowVO();
                BeanUtils.copyProperties(item, articleShowVO);
                articleShowVO.setCommentNum(0L);
                articleShowVO.setTag("无标签");
                // 评论数
                if (CollectionUtils.isNotEmpty(articleComments)) {
                    articleShowVO.setCommentNum(articleComments.stream().filter(comment -> comment.getArticleId().equals(item.getId())).count());
                }
                // 标签
                if (CollectionUtils.isNotEmpty(tags)) {
                    String tagIds = item.getTagId();
                    Set<Long> tagIdSet = Arrays.stream(tagIds.split(",")).map(Long::parseLong).collect(Collectors.toSet());
                    List<String> list = tags.stream().filter(tag -> tagIdSet.contains(tag.getId())).map(ArticleTagEntity::getTagName).collect(Collectors.toList());
                    //TODO 标签列表，这里只显示了一个
                    if (CollectionUtils.isNotEmpty(list)) {
                        articleShowVO.setTag(list.get(0));
                    }
                }
                String prefix = SysDictionaries.getValue(DictionariesKey.SYS_MINIO_SITE);
                articleShowVO.setArticleImages(prefix+item.getArticleImages());
                //发布时间
                articleShowVO.setCreateTime(DateUtil.formatDateTime(item.getCreateTime()));
                //更新时间
                articleShowVO.setUpdateTime(DateUtil.formatDateTime(item.getUpdateTime()));
                return articleShowVO;
            }).collect(Collectors.toList());
            PageResultVO<ArticleShowVO> articleShowVOPageResultVO = PageUtil.buildPageResultVO(articleEntityPage, articleShowVOS);
            return R.success(articleShowVOPageResultVO);
        }

        return R.success(PageUtil.convert2PageEmptyResult(articleEntityPage, ArticleShowVO.class));

    }

    @Override
    public R<Void> feedback(FeedBackDTO dto) {
        String url = dto.getUrl();
        Long userId = checkUrl(url);
        if (Objects.isNull(userId)) {
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        FeedbackEntity feedbackEntity = new FeedbackEntity();
        feedbackEntity.setMsg(dto.getMsg());
        feedbackEntity.setEmail(dto.getEmail());
        feedbackEntity.setStatus(FeedbackEnum.WAITING.getCode());
        feedbackEntity.setTenantId(userId);
        String ip = RequestUtil.getIp();
        feedbackEntity.setIp(ip);
        feedbackEntity.setIpAddr(RequestUtil.getPlace(ip));
        feedbackService.save(feedbackEntity);
        SpringUtil.publishEvent(new ClearHomeArticleCacheEvent(this, userId));
        return R.success();
    }

    @Override
    public R<PageResultVO<FeedbackWebVO>> getFeedbackList(Integer pageNum, Integer pageSize, String url) {
        UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));
        if (Objects.isNull(user)) {
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        Page<FeedbackEntity> page = new Page<>(pageNum, pageSize);
        Page<FeedbackEntity> feedbackEntityPage = feedbackService.page(page, new LambdaQueryWrapper<FeedbackEntity>().eq(FeedbackEntity::getTenantId, user.getId()));
        List<FeedbackEntity> records = feedbackEntityPage.getRecords();
        if (!Objects.isNull(records)) {
            List<FeedbackWebVO> feedbackWebVOS = records.stream().map(item -> {
                FeedbackWebVO feedbackWebVO = new FeedbackWebVO();
                BeanUtils.copyProperties(item, feedbackWebVO);
                feedbackWebVO.setMsg(item.getMsg());
                feedbackWebVO.setStatus(FeedbackEnum.getStatus(item.getStatus()));
                feedbackWebVO.setDate(DateUtil.formatDateTime(item.getCreateTime()));
                return feedbackWebVO;
            }).collect(Collectors.toList());
            PageResultVO<FeedbackWebVO> pageResultVO = PageUtil.buildPageResultVO(feedbackEntityPage, feedbackWebVOS);
            return R.success(pageResultVO);
        }
        return R.success(PageUtil.convert2PageEmptyResult(feedbackEntityPage, FeedbackWebVO.class));
    }

    @Override
    public R<ArticleTextVO> getArticleDetail(Long id,String url) {
        if(Objects.nonNull(ExistCache.get(ExistCache.ARTICLE_PREFIX.concat(id.toString()))) ||
            Objects.nonNull(ExistCache.get(ExistCache.HOME_PREFIX.concat(url)))){

            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));
        if (Objects.isNull(user)) {
            ExistCache.put(ExistCache.HOME_PREFIX.concat(url));
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        ArticleTextVO articleTextCache = ArticleDetailCache.get(id);
        if (Objects.nonNull(articleTextCache)) {
            addArticleViewCount(id,user.getId());
            return R.success(articleTextCache);
        }
        synchronized (ExistCache.ARTICLE_PREFIX.concat(id.toString()).intern()){
            ArticleTextVO articleTextCacheTwo = ArticleDetailCache.get(id);
            if (Objects.nonNull(articleTextCacheTwo)) {
                return R.success(articleTextCacheTwo);
            }
            ArticleTextVO articleTextVO = new ArticleTextVO();
            ArticleEntity articleEntity = this.blogArticleMapper.selectOne(new LambdaQueryWrapper<ArticleEntity>().eq(ArticleEntity::getId, id).eq(ArticleEntity::getTenantId, user.getId()).eq(ArticleEntity::getStatus,ArticleEnum.UP.getCode()));
            if (Objects.isNull(articleEntity)){
                ExistCache.put(ExistCache.ARTICLE_PREFIX.concat(id.toString()));
                return R.error("文章不存在");
            }
            String prefix = SysDictionaries.getValue(DictionariesKey.SYS_MINIO_SITE);
            String zwf = SysDictionaries.getValue(DictionariesKey.IMG_ZWF);

            CompletableFuture<Void> textFuture = CompletableFuture.runAsync(() -> {
                ArticleTextEntity textEntity = this.articleTextService.getOne(new LambdaQueryWrapper<ArticleTextEntity>().eq(ArticleTextEntity::getArticleId, id).eq(ArticleTextEntity::getStatus, ArticleEnum.UP.getCode()));
                String articleFullText = textEntity.getArticleFullText();
                String value = articleFullText.replace(zwf, prefix);
                articleTextVO.setContent(value);
                articleTextVO.setTitle(articleEntity.getTitle());
                articleTextVO.setImgUrl(prefix.concat(articleEntity.getArticleImages()));

                articleTextVO.setCreateTime(DateUtil.formatDateTime(articleEntity.getCreateTime()));
                articleTextVO.setCategory(articleEntity.getClassification());
            }, mainThreadPool);
            CompletableFuture<Void> tagFuture = CompletableFuture.runAsync(() -> {
                String tagIdStr = articleEntity.getTagId();
                String[] ids = tagIdStr.split(",");
                Set<Long> idsList = Arrays.stream(ids).map(Long::parseLong).collect(Collectors.toSet());
                List<ArticleTagEntity> list = this.articleTagService.list(new LambdaQueryWrapper<ArticleTagEntity>().in(ArticleTagEntity::getId, idsList));
                if (CollectionUtils.isNotEmpty(list)) {
                    List<String> tags = list.stream().map(ArticleTagEntity::getTagName).collect(Collectors.toList());
                    articleTextVO.setTags(tags);
                } else {
                    articleTextVO.setTags(new ArrayList<>());
                }

            }, mainThreadPool);
            CompletableFuture<Void> commentFuture = CompletableFuture.runAsync(() -> {
                R<List<ArticleCommentVO>> comment = getComment(id);
                if (BaseEnum.commonEnum.SUCCESS.getCode().equals(comment.getCode()) && CollectionUtils.isNotEmpty(comment.getData())) {
                    articleTextVO.setCommentVOList(comment.getData());
                }else {
                    articleTextVO.setCommentVOList(new ArrayList<>());
                }
            }, mainThreadPool);
            CompletableFuture<Void> authorFuture = CompletableFuture.runAsync(() -> {
                HomeDetail authorName = this.homeDetailService.getOne(new LambdaQueryWrapper<HomeDetail>().eq(HomeDetail::getTenantId, user.getId())
                        .select(HomeDetail::getAuthorName,HomeDetail::getAuthorHeaderImg,HomeDetail::getBlogTitle,HomeDetail::getBlogTitleEnglish));

                if (Objects.nonNull(authorName)) {
                    articleTextVO.setAuthorName(authorName.getAuthorName());
                    articleTextVO.setAuthorHeadImgUrl(prefix.concat(authorName.getAuthorHeaderImg()));
                    articleTextVO.setBlogTitle(authorName.getBlogTitle());
                    articleTextVO.setBlogTitleEnglish(authorName.getBlogTitleEnglish());
                } else {
                    articleTextVO.setAuthorName("无名");
                }
            }, mainThreadPool);
            CompletableFuture.allOf(textFuture, tagFuture, commentFuture,authorFuture).join();
            ArticleDetailCache.put(id, articleTextVO);
            addArticleViewCount(id,user.getId());
            return R.success(articleTextVO);
        }

    }

    /**
     * 增加文章阅读数
     * @param articleId 文章id
     * @param userId 用户id
     */
    private void addArticleViewCount(Long articleId,Long userId) {
        mainThreadPool.execute(()->{
            HomeVO homeVO = HomeCache.get(userId);
            //在首页，更新推荐文章缓存阅读数
            Optional.ofNullable(homeVO).map(HomeVO::getRecommendArticleList)
                    .flatMap(item -> item.stream().filter(item1 -> item1.getId().equals(articleId)).findFirst())
                    .ifPresent(item2 -> item2.setReadNum(item2.getReadNum() + 1));
            //持久化，数据不精确，有并发问题
            try {
                ArticleEntity articleEntity = this.blogArticleMapper.selectById(articleId);
                if(Objects.nonNull(articleEntity)){
                    ArticleEntity article = new ArticleEntity();
                    article.setId(articleId);
                    article.setReadNum(articleEntity.getReadNum() + 1);
                    this.blogArticleMapper.updateById(article);
                }
            }catch (Exception e){
                log.error("增加阅读数失败:id={},userId={}",articleId,userId);
            }
        });
    }
    @Override
    public R<Void> comment(CommentDTO dto) {
        ArticleComment articleComment = new ArticleComment();
        articleComment.setArticleId(dto.getArticleId());
        articleComment.setCommentContent(dto.getContent());
        articleComment.setParentId(dto.getParentId());
        articleComment.setEmail(dto.getEmail());
        if(!dto.getParentId().equals(0L) && Objects.nonNull(dto.getToEmail())){
            //TODO 回复邮件通知
        }
        articleComment.setName(dto.getName());
        //TODO 评论内容脱敏
        articleComment.setCommentContentDesensitization(dto.getContent());
        String ip = RequestUtil.getIp();
        articleComment.setIp(ip);
        articleComment.setIpAddress(RequestUtil.getPlace(ip));
        articleComment.setAiDistinguishing(CommentEnum.NO_AI_DISTINGUISHING.getCode());
        articleComment.setIsAuthor(0);
        articleComment.setToName(dto.getToName());
        this.articleCommentService.save(articleComment);

        mainThreadPool.execute(()->{
            SpringUtil.publishEvent(new ClearWebArticleDetailEvent(this, dto.getArticleId()));
            ArticleEntity articleEntity = this.blogArticleMapper.selectOne(new LambdaQueryWrapper<ArticleEntity>().eq(ArticleEntity::getId, dto.getArticleId()));
            SiteLetterEntity siteLetterEntity = Letter.builder(LetterEnum.LetterType.SYS_SEND.getCode(), LetterEnum.SysSubjectType.COMMENT_EVENT.getSubject(articleEntity.getTitle()),
                    Letter.builderCommentContent(dto.getContent(),
                            dto.getName(), dto.getToName(),
                            dto.getEmail(), dto.getToEmail()), articleEntity.getTenantId(), 0);
            SpringUtil.publishEvent(new LetterEvent(this, siteLetterEntity));
        });

        return R.success();
    }

    @Override
    public R<List<ArticleCommentVO>> getComment(Long id) {
        List<ArticleComment> list = this.articleCommentService.list(new LambdaQueryWrapper<ArticleComment>().eq(ArticleComment::getArticleId, id));
        if (CollectionUtils.isNotEmpty(list)) {
            List<ArticleCommentVO> rootNodes = list.stream().filter(item -> item.getParentId().equals(0L)).map(item -> {
                ArticleCommentVO articleCommentVO = new ArticleCommentVO();
                BeanUtils.copyProperties(item, articleCommentVO);
                articleCommentVO.setCreateTime(DateUtil.formatDateTime(item.getCreateTime()));
                articleCommentVO.setCommentContent(item.getCommentContentDesensitization());
                return articleCommentVO;
            }).sorted(Comparator.comparing(ArticleCommentVO::getCreateTime,Comparator.nullsFirst(String::compareTo)).reversed()).collect(Collectors.toList());
            for (ArticleCommentVO rootNode : rootNodes) {
                List<ArticleCommentVO> children = list.stream().filter(item -> item.getParentId().equals(rootNode.getId())).map(item -> {
                    ArticleCommentVO articleCommentVO = new ArticleCommentVO();
                    BeanUtils.copyProperties(item, articleCommentVO);
                    articleCommentVO.setCreateTime(DateUtil.formatDateTime(item.getCreateTime()));
                    articleCommentVO.setCommentContent(item.getCommentContentDesensitization());
                    return articleCommentVO;
                }).sorted(Comparator.comparing(ArticleCommentVO::getCreateTime,Comparator.nullsFirst(String::compareTo).reversed())).collect(Collectors.toList());
                rootNode.setChildren(children);
            }
            return R.success(rootNodes);
        }
        return R.success(new ArrayList<>());
    }
    private Long checkUrl(String url) {
        if(Objects.nonNull(ExistCache.get(ExistCache.HOME_PREFIX.concat(url)))){
            return null;
        }
        UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));

        if (Objects.isNull(user)) {
            ExistCache.put(ExistCache.HOME_PREFIX.concat(url));
            return null;
        }
        return user.getId();
    }
    @Override
    public R<?> getSayList(Integer length, String url) {
        Long userId = checkUrl(url);
        if(Objects.isNull(userId)){
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        SayHomeVO sayHomeVO = new SayHomeVO();
        CompletableFuture<Void> authorFuture = null;
        if(IntegerConstant.ZERO.equals(length)){

             authorFuture = CompletableFuture.runAsync(() -> {
                HomeDetail author = this.homeDetailService.getOne(new LambdaQueryWrapper<HomeDetail>().eq(HomeDetail::getTenantId, userId));
                 log.info("author:{}",author);
                if (Objects.nonNull(author)) {
                    String prefix = SysDictionaries.getValue(DictionariesKey.SYS_MINIO_SITE);
                    sayHomeVO.setAuthorName(author.getAuthorName());
                    sayHomeVO.setAuthorHeadImg(prefix.concat(author.getAuthorHeaderImg()));
                    sayHomeVO.setBlogTitle(author.getBlogTitle());
                    sayHomeVO.setBlogTitleEnglish(author.getBlogTitleEnglish());
                }
            }, mainThreadPool);
        }
        int count = this.moodService.count(new LambdaQueryWrapper<MoodEntity>().eq(MoodEntity::getTenantId, userId));
        sayHomeVO.setCount(count);
        List<MoodEntity> moodEntities = this.moodService.list(new LambdaQueryWrapper<MoodEntity>().eq(MoodEntity::getTenantId, userId)
                .eq(MoodEntity::getStatus, MoodConstants.PUBLISH_MOOD)
                .orderByDesc(MoodEntity::getIsTop)
                .orderByDesc(MoodEntity::getSortNum)
                .orderByDesc(MoodEntity::getCreateTime)
                .last("limit "+ length + ", 5"));
        if(CollectionUtils.isNotEmpty(moodEntities)){
            List<SayVO> sayVOS = moodEntities.stream().map(item -> {
                SayVO sayVO = new SayVO();
                BeanUtils.copyProperties(item, sayVO);
                sayVO.setCreateTime(DateUtil.formatDateTime(item.getCreateTime()));
                return sayVO;
        }).collect(Collectors.toList());
            sayHomeVO.setSayList(sayVOS);
        }else{
            sayHomeVO.setSayList(new ArrayList<>());
        }
        if(Objects.nonNull(authorFuture)){
            authorFuture.join();
        }
        return R.success(sayHomeVO);
    }

    @Override
    public R<SocialEntity> getSocial(String url) {
        if(Objects.nonNull(ExistCache.get(ExistCache.HOME_PREFIX.concat(url)))){
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }

        //社交数据
        UserEntity entity = this.userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));

        if(Objects.isNull(entity)){
            ExistCache.put(ExistCache.HOME_PREFIX.concat(url));
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        SocialEntity result = this.socialService.getOne(new LambdaQueryWrapper<SocialEntity>().eq(SocialEntity::getTenantId, entity.getId()));
        return R.success(result);
    }

    @Override
    public R<BackGroundVO> getBackGround(String url) {
        if(Objects.nonNull(ExistCache.get(ExistCache.HOME_PREFIX.concat(url)))){
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }

        UserEntity user = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUrl, url));
        if(Objects.isNull(user)){
            ExistCache.put(ExistCache.HOME_PREFIX.concat(url));
            return R.error(BaseEnum.authEnum.USER_NOT_EXIST);
        }
        BackGroundVO backGroundVO = new BackGroundVO();
        HomeDetail homeDetail = this.homeDetailService.getOne(new LambdaQueryWrapper<HomeDetail>().eq(HomeDetail::getTenantId, user.getId()));
        String prefix = SysDictionaries.getValue(DictionariesKey.SYS_MINIO_SITE);
        if(Objects.nonNull(homeDetail)) {
            backGroundVO.setImgUrl(prefix + homeDetail.getFm());
            backGroundVO.setEnglishTitle(homeDetail.getBlogTitleEnglish());
            backGroundVO.setTitle(homeDetail.getBlogTitle());
            backGroundVO.setSign(homeDetail.getSign());
            backGroundVO.setDySign(homeDetail.getDynamicSign());
            backGroundVO.setAuthorImg(prefix+homeDetail.getAuthorHeaderImg());
        }
        return R.success(backGroundVO);
    }

    @Override
    public R<Void> goodsArticle(Long id) {

        ArticleEntity articleEntity = this.blogArticleMapper.selectById(id);
        if(Objects.isNull(articleEntity)){
            return R.error("文章不存在");
        }
        articleEntity.setGoodsNum(articleEntity.getGoodsNum() + 1);
        this.blogArticleMapper.updateById(articleEntity);
        SpringUtil.publishEvent( new ClearHomeArticleCacheEvent(this,articleEntity.getTenantId()));
        return R.success();
    }


}

